package com.caowei.weicimpress.weicimpress;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

/**
 * Created by caoweiPc on 2014/7/18.
 */
public class ExecuteFileHandler {
    private static final String TAG=ExecuteFileHandler.class.getSimpleName();
    private List<FileHandler> fileHandlers=new ArrayList<FileHandler>();
    private List<Class<? extends FileHandler>> notCompressHandlerClses=new ArrayList<Class<? extends FileHandler>>();
    private static ExecuteFileHandler instance;
    private Queue<Runnable> asyncQueue=new ConcurrentLinkedQueue<Runnable>();
    private List<AsyncTask> asyncTasks=new ArrayList<AsyncTask>();

    //todo  暂定
    private boolean async=true;
    private Thread thread;

    //todo  暂定
    public void submitAsyncRunable(Runnable runnable){
        asyncQueue.add(runnable);
        if(thread!=null){
            thread.interrupt();
        }
    }
    //todo  暂定
    private ExecuteFileHandler(){
        Context context=ActivityManager.getInstance().peekTop().getApplicationContext();
        List<Class> cles= Utils.getSubClsFromParent(context,FileHandler.class);
        for(Class cl:cles){
            try {
                Constructor<FileHandler> constructor= cl.getConstructor(Context.class);
                constructor.setAccessible(true);
                FileHandler handler= constructor.newInstance(ActivityManager.getInstance().peekTop().getApplicationContext());
                fileHandlers.add(handler);
                notCompressHandlerClses.add(SysFileHandler.class);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

        Collections.sort(fileHandlers, new Comparator<FileHandler>() {
            @Override
            public int compare(FileHandler lhs, FileHandler rhs) {
                return lhs.compare(rhs);
            }
        });
    };

    public  boolean checkCompressNoFinished(FileInfoBean bean){
        for(FileHandler fileHandler:fileHandlers){
            File file=new File(Utils.normalizePath(bean.getParentPath()+File.separator+
            bean.getFileName()));
            if(fileHandler.checkCompressNoFinished(file)){
                return true;
            }
        }
        return false;
    }

    public  void clear(){
        if(asyncTasks!=null&&!asyncTasks.isEmpty()){
            for(AsyncTask task:asyncTasks){
                if(task!=null&&(task.getStatus().equals(AsyncTask.Status.PENDING)
                        ||task.getStatus().equals(AsyncTask.Status.RUNNING))){
                    task.cancel(true);
                    task=null;
                }
            }
            asyncTasks.clear();
            asyncTasks=null;
        }
        async=false;
        asyncQueue.clear();
        asyncQueue=null;

        fileHandlers.clear();
        fileHandlers=null;
        instance=null;
    }

    public static ExecuteFileHandler getInstance(){
        synchronized (ExecuteFileHandler.class){
            if(instance==null){
                instance=new ExecuteFileHandler();
                //启动异步程
               instance.thread =new Thread(){
                    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
                    @Override
                    public void run() {
                        while (true){
                            Log.d(TAG,"轮循中");
                            if(!instance.async){
                                break;
                            }
                            if(!instance.asyncQueue.isEmpty()){
                                instance.asyncQueue.remove().run();
                            }else{
                                try {
                                    Log.d(TAG,"sleep");
//                                    TimeUnit.MILLISECONDS.sleep(10000);
                                    if(Build.VERSION_CODES.GINGERBREAD>Build.VERSION.SDK_INT){
                                        TimeUnit.MINUTES.sleep(Utils.MAXSLEEPTIME);
                                    }else{
                                        Thread.sleep(Utils.MAXSLEEPTIME);
                                    }
                                } catch (InterruptedException e) {
                                    Log.d(TAG, "中断sleep");
                                    //恢复中断
                                    Thread.currentThread().interrupt();
                                    e.printStackTrace();
                                }
                            }
                        }
                        Log.d(TAG,"轮循停止");
                    }
                };

                instance.thread.start();
            }
        }
        return instance;
    }

    public FileHandler getHandlerByFile(File file){
        FileHandler fileHandler=null;
        if(file!=null){
            for(FileHandler handler:fileHandlers){
                if(handler.isThisHandler(file)){
                    return handler;
                }
            }
        }
        return fileHandler;
    }

    public FileHandler getHandlerByClsName(String clsName){
        FileHandler fileHandler=null;
        if(!TextUtils.isEmpty(clsName)){
            for(FileHandler handler:fileHandlers){
                if(handler.getClass().getName().equals(clsName)){
                    return handler;
                }
            }
        }
        return fileHandler;
    }

    public List<FileHandler> getSupportCompressHandlers(){
       List<FileHandler> result=new ArrayList<FileHandler>();
       for(FileHandler handler:fileHandlers){
           if(handler!=null&&!notCompressHandlerClses.contains(handler.getClass())){
               result.add(handler);
           }
       }
        return result;
    }


    public boolean isCompressFile(File file){
        FileHandler fileHandler=getHandlerByFile(file);
        if(fileHandler!=null&&!notCompressHandlerClses.contains(fileHandler.getClass())){
            return true;
        }
        return false;
    }

    public boolean isCompressFileHandler(FileHandler fileHandler){
        if(fileHandler!=null&&!notCompressHandlerClses.contains(fileHandler.getClass())){
            return true;
        }
        return false;
    }

    public boolean isEncried(File file){
        boolean result=false;
        FileHandler fileHandler=getHandlerByFile(file);
        result=fileHandler.isEncried(file);
        return result;
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void execute(FileInfoBean operFile,FileHandler.OperType optype,FragHandlerHub hub){
        AsyncTask  asyncTask=new  AsyncTask<Object,Object,Object[]>(){
            @Override
            protected Object[] doInBackground(Object... params) {
                FileInfoBean operFile= (FileInfoBean) params[0];
                FileHandler.OperType operType= (FileHandler.OperType) params[1];
                FragHandlerHub hub= (FragHandlerHub) params[2];
                for(FileHandler handler:fileHandlers){
                    if(handler.isThisHandler(operFile.getRootFile())){
                        switch (operType){
                            case LIST:
                                MyDataList dataList= handler.list(operFile);
                                return new Object[]{dataList,operType,hub};
                            case COMPRESS:
                                break;
                            case EXTRACT:
                                break;
                        }
                        break;
                    }
                }
                return  new Object[]{null,operType,hub};
            }

            @Override
            protected void onPostExecute(Object[] o) {
                FragHandlerHub hub= (FragHandlerHub) o[2];
                hub.execute(o);
                if(asyncTasks.contains(this)){
                    asyncTasks.remove(this);
                }
            }
        };
        asyncTasks.add(asyncTask);
        if(Build.VERSION.SDK_INT<Build.VERSION_CODES.HONEYCOMB){
            asyncTask.execute(operFile,optype,hub);
        }else{
//            asyncTask.execute(operFile,optype,hub);
            asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,operFile,optype,hub);
        }
    }


    private  class ExeFileHandlerAsyncTask extends AsyncTask<Object,Object,Object[]>{
        @Override
        protected Object[] doInBackground(Object... params) {
            FileInfoBean operFile= (FileInfoBean) params[0];
            FileHandler.OperType operType= (FileHandler.OperType) params[1];
            FragHandlerHub hub= (FragHandlerHub) params[2];
            for(FileHandler handler:fileHandlers){
                if(handler.isThisHandler(operFile.getRootFile())){
                    switch (operType){
                        case LIST:
                           MyDataList dataList= handler.list(operFile);
                            return new Object[]{dataList,operType,hub};
                        case COMPRESS:
                            break;
                        case EXTRACT:
                            break;
                    }
                    break;
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Object[] o) {
            FragHandlerHub hub= (FragHandlerHub) o[2];
            hub.execute(o);
            if(asyncTasks.contains(this)){
                asyncTasks.remove(this);
            }
        }
    }
}
